/*
 * Step.java
 *
 * Created on July 31, 2006, 9:00 AM
 *
 * (C) R. Alexander Milowski alex@milowski.com
 */

package com.smallx.xproc;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.infoset.xml.Name;
import org.infoset.xml.NamespaceScope;

/**
 *
 * @author R. Alexander Milowski
 */
public class Step extends ModelItem {

   StepContainer container;
   ComponentType type;
   Map<Name, Reference> inputBinding;
   Map<Name, Set<PortReference>> outputBinding;
   Map<Name,String> parameters;
   NamespaceScope scope;
   
   /** Creates a new instance of Step */
   public Step(ComponentType type,StepContainer container,Name name,NamespaceScope scope) {
      super(name);
      this.container = container;
      this.type = type;
      this.inputBinding = new HashMap<Name,Reference>();
      this.outputBinding = new HashMap<Name,Set<PortReference>>();
      this.parameters = null;
      this.scope = scope;
   }
   
   public NamespaceScope getNamespaceScope() {
      return scope;
   }
   
   public StepContainer getContainer() {
      return container;
   }
   
   public ComponentType getComponentType() {
      return type;
   }
   
   public Set<Name> getInputBindings() {
      return inputBinding.keySet();
   }
   
   public Reference getInputBinding(Name name) {
      return inputBinding.get(name);
   }
   
   public Set<Name> getOutputBindings() {
      return outputBinding.keySet();
   }
   
   public Set<PortReference> getOutputBinding(Name name) {
      return outputBinding.get(name);
   }
   
   public boolean hasParameters() {
      return parameters!=null ? parameters.keySet().size()!=0 : false;
   }
   
   public Map<Name,String> getParameters() {
      if (parameters==null) {
         parameters = new HashMap<Name,String>();
      }
      return parameters;
   }
   
   public void bindInput(Name name,Reference ref) 
      throws ModelErrorException
   {
      if (type.getInputPort(name)==null && !type.hasArbitraryInputs()) {
         throw new ModelErrorException("There is no input port named "+name+" on "+type.getName(),this);
      }
      if (inputBinding.get(name)!=null) {
         throw new ModelErrorException("Binding for input port "+name+" already exists on "+this.getName(),this);
      }
      inputBinding.put(name,ref);
   }
   public void bindOutput(Name name,PortReference ref) 
      throws ModelErrorException
   {
      if (type.getOutputPort(name)==null) {
         throw new ModelErrorException("There is no output port named "+name+" on "+type.getName(),this);
      }
      Set<PortReference> bindings = outputBinding.get(name);
      if (bindings==null) {
         bindings = new HashSet<PortReference>();
         outputBinding.put(name,bindings);
      }
      bindings.add(ref);
   }

   
}
